package contents;

import common.CommonMethods;
import contents.entities.Absence;
import contents.entities.Teacher;
import contents.entities.Class;
import contents.entities.ClassesStudents;
import contents.entities.DateSubstitutions;
import contents.entities.Student;
import contents.entities.Subject;
import contents.entities.SubstitutionItem;
import contents.entities.SubstitutionToSolve;
import database.Database;
import database.DatabaseEntities;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import servlets.ApplicationServlet;
import servlets.FileUploadServlet;

public class AdminContent {
    private static String informationForTimetablesFilePath;
    
    public static void setInformationForTimetablesFilePath() {
        informationForTimetablesFilePath = ApplicationServlet.getServletPath() + File.separator + "informationForTimetables.xml";
    }
    

    public static HttpServletRequest setContent(HttpServletRequest request) 
            throws SQLException, ParserConfigurationException, TransformerConfigurationException, TransformerException, IOException, SAXException, ParseException {
        String contentRequest = (String) request.getParameter("content");

        if (contentRequest == null) {
            // do nothing
        } else if (contentRequest.equals("absences")) {
            request = setAbsencesContent(request);
        } else if (contentRequest.equals("deleteAbsence")) {
            deleteAbsence(request);
        } else if (contentRequest.equals("addAbsence")) {
            request = addAbsence(request);
            
        } else if (contentRequest.equals("substitutions")) {
            request = setSubstitutionsContent(request);
        } else if (contentRequest.equals("deleteSubstitution")) {
            deleteSubstitution(request);
        } else if (contentRequest.equals("setSubstitutionForm")) {
            request = setSetSubstitutionContent(request);
        } else if (contentRequest.equals("setSubstitution")) {
            setSubstitution(request);
            
        } else if (contentRequest.equals("subjects")) {
            request = setSubjectsContent(request);
        } else if (contentRequest.equals("addSubject")) {
            request = addSubject(request);
        } else if (contentRequest.equals("editSubject")) {
            request = editSubject(request);
        } else if (contentRequest.equals("deleteSubject")) {
            deleteSubject(request);
            
        } else if (contentRequest.equals("classes")) {
            request = setClassesContent(request);
        } else if (contentRequest.equals("addClass")) {
            request = addClass(request);
        } else if (contentRequest.equals("editClass")) {
            request = editClass(request);
        } else if (contentRequest.equals("deleteClass")) {
            request = deleteClass(request);
            
        } else if (contentRequest.equals("teachers")) {
            request = setTeachersContent(request);
        } else if (contentRequest.equals("addTeacherForm")) {
            request = setAddTeacherContent(request);
        } else if (contentRequest.equals("addTeacher")) {
            request = addTeacher(request);
        } else if (contentRequest.equals("newTeacherAdded")) {
            request = setTeacherAddedContent(request);
        } else if (contentRequest.equals("editTeacherForm")) {
            request = setEditTeacherContent(request);
        } else if (contentRequest.equals("editTeacher")) {
            request = editTeacher(request);
        } else if (contentRequest.equals("newPasswordForTeacher")) {
            request = createNewPasswordForTeacher(request);
        } else if (contentRequest.equals("newPasswordForTeacherCreated")) {
            request = setNewPasswordForTeacherCreatedContent(request);
        } else if (contentRequest.equals("deleteTeacher")) {
            deleteTeacher(request);
            
        } else if (contentRequest.equals("students")) {
            request = setStudentsContent(request);
        } else if (contentRequest.equals("addStudentForm")) {
            request = setAddStudentContent(request);
        } else if (contentRequest.equals("addStudent")) {
            request = addStudent(request);
        } else if (contentRequest.equals("newStudentAdded")) {
            request = setStudentAddedContent(request);
        } else if (contentRequest.equals("editStudentForm")) {
            request = setEditStudentContent(request);
        } else if (contentRequest.equals("editStudent")) {
            request = editStudent(request);
        } else if (contentRequest.equals("newPasswordForStudent")) {
            request = createNewPasswordForStudent(request);
        } else if (contentRequest.equals("newPasswordForStudentCreated")) {
            request = setNewPasswordForStudentCreatedContent(request);
        } else if (contentRequest.equals("newPasswordForParent")) {
            request = createNewPasswordForParent(request);
        } else if (contentRequest.equals("newPasswordForParentCreated")) {
            request = setNewPasswordForParentCreatedContent(request);
        } else if (contentRequest.equals("deleteStudent")) {
            deleteStudent(request);
            
        } else if (contentRequest.equals("timetables")) {
            request = setTimetablesContent(request);
        } else if (contentRequest.equals("downloadXMLInformationForTimetables")) {
            makeFileOfXMLInformationForTimetables(request);
        } else if (contentRequest.equals("deleteTimetable")) {
            deleteTimetable(request);
        } else if (contentRequest.equals("setTimetable")) {
            deleteTimetable(request);
            request = setTimetable(request);
        } else if (contentRequest.equals("setTimetableSuccessful")) {
            request = setTimetableSetSuccessfulContent(request);
        }

        return request;
    }
    
    private static HttpServletRequest setAbsencesContent(HttpServletRequest request) throws SQLException {
        java.util.Date tomorrowDate = new java.util.Date();
        tomorrowDate.setDate(tomorrowDate.getDate() + 1);
        Map<Integer, Absence> absences = Database.selectAllAbsencesSinceDate(tomorrowDate);
        request.setAttribute("absences", absences.values());
        
        Map<Integer, Teacher> teachers = Database.selectTeachers();
        
        request.setAttribute("teachers", teachers.values());
        return request;
    }
    
    private static void deleteAbsence(HttpServletRequest request) throws SQLException {
        int absenceId = Integer.valueOf(request.getParameter("absenceId")).intValue();
        
        Database.deleteAbsence(absenceId);
    }
    
    private static HttpServletRequest addAbsence(HttpServletRequest request) throws SQLException, ParseException {
        int teacherId = Integer.valueOf(request.getParameter("teacherId")).intValue();
        
        String dateString = request.getParameter("date");
        java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat("dd.MM.yyyy");
        java.util.Date date = dateFormat.parse(dateString);
        java.util.Date currentDate = new java.util.Date();
        if (currentDate.compareTo(date) >= 0) {
            request.setAttribute("result", "failed");
            request.setAttribute("action", "addAbsence");
            return request;
        }
        
        int fromUnit = Integer.valueOf(request.getParameter("fromUnit"));
        int toUnit = Integer.valueOf(request.getParameter("toUnit"));
        
        Database.addAbsence(teacherId, date, fromUnit, toUnit);
        request.setAttribute("redirect", "absences");
        return request;
    }
    
    private static HttpServletRequest setSubstitutionsContent(HttpServletRequest request) throws SQLException, ParseException {
        request = setExistingSubstitutionsContent(request);
        request = setNonExistingSubstitutionsContent(request);
        
        return request;
    }
    
    private static HttpServletRequest setExistingSubstitutionsContent(HttpServletRequest request) throws SQLException, ParseException {
        // get substitutions since today
        java.util.Date currentDate = new java.util.Date();
        List<DatabaseEntities.Substitution> substitutions = Database.selectSubstitutionsSinceDate(currentDate);
        
        Map<java.util.Date, List<SubstitutionItem> > dateSubstitutionsMap = new HashMap<java.util.Date, List<SubstitutionItem> > ();
        
        for (int i = 0; i < substitutions.size(); i++) {
            DatabaseEntities.Substitution substitution = substitutions.get(i);
            
            int substitutionId = substitution.substitutionId;
            String className = Database.selectClassName(substitution.classId);
            Integer lesson = Integer.valueOf(substitution.unit);
            Subject subject = Database.getSubject(substitution.subjectId);
            Teacher missingTeacher = Database.getTeacher(substitution.missingTeacherId);
            
            Teacher substitutingTeacher;
            if (substitution.substitutingTeacherId == null) {
                substitutingTeacher = null;
            } else {
                substitutingTeacher = Database.getTeacher(substitution.substitutingTeacherId.intValue());
            }

            java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd");
            java.util.Date date = dateFormat.parse(substitution.dateString);
            boolean foundDate = false;
            for (Map.Entry<java.util.Date, List<SubstitutionItem> > entry : dateSubstitutionsMap.entrySet()) {
                if (entry.getKey().equals(date)) {
                    foundDate = true;
                    break;
                }
            }
            if (!foundDate) {
                dateSubstitutionsMap.put(date, new ArrayList<SubstitutionItem>());
            }
            
            dateSubstitutionsMap.get(date).add(new SubstitutionItem(substitutionId, className, lesson, subject, missingTeacher, substitutingTeacher));
        }
        
        Map<Integer, DateSubstitutions> dateSubstitutions = new HashMap<Integer, DateSubstitutions>();
        int i = 1;
        for (Map.Entry<java.util.Date, List<SubstitutionItem> > entry : dateSubstitutionsMap.entrySet()) {
            Collections.sort(entry.getValue(), new SubstitutionItem.ByClassNameAndTimeComparator());
            dateSubstitutions.put(i, new DateSubstitutions(entry.getKey(), entry.getValue()));
            i++;
        }
        
        request.setAttribute("substitutions", dateSubstitutions.values());
        return request;
    }
    
    private static HttpServletRequest setNonExistingSubstitutionsContent(HttpServletRequest request) throws SQLException {
        // get substitutions to solve since today
        java.util.Date currentDate = new java.util.Date();
        Map<Integer, SubstitutionToSolve> substitutionsToSolve = Database.selectSubstitutionsToSolveSinceDate(currentDate);
        request.setAttribute("substitutionsToSolve", substitutionsToSolve.values());
        
        return request;
    }
    
    private static void deleteSubstitution(HttpServletRequest request) throws SQLException {
        int substitutionId = Integer.valueOf(request.getParameter("substitutionId")).intValue();
        
        Database.deleteSubstitution(substitutionId);
    }
    
    private static HttpServletRequest setSetSubstitutionContent(HttpServletRequest request) throws SQLException {
        int absenceId = Integer.valueOf(request.getParameter("absenceId")).intValue();
        int timetableId = Integer.valueOf(request.getParameter("timetableId")).intValue();
        
        SubstitutionToSolve substitutionToSolve = Database.getSubstitutionToSolve(timetableId, absenceId);
        request.setAttribute("substitutionToSolve", substitutionToSolve);
        
        Map<Integer, Teacher> unoccupiedTeachers = Database.selectUnoccupiedTeachersForSubstitution(timetableId, absenceId);        
        request.setAttribute("unoccupiedTeachers", unoccupiedTeachers.values());
        
        return request;
    }
    
    private static void setSubstitution(HttpServletRequest request) throws SQLException {
        int absenceId = Integer.valueOf(request.getParameter("absenceId")).intValue();
        int timetableId = Integer.valueOf(request.getParameter("timetableId")).intValue();
        int substitutingTeacherId = Integer.valueOf(request.getParameter("substitutingTeacherId")).intValue();
        Teacher substitutor;
        if (substitutingTeacherId == -1) {
            substitutor = null;
        } else {
            substitutor = Database.getTeacher(substitutingTeacherId);
        }

        Database.setSubstitution(absenceId, timetableId, substitutor);
    }

    private static HttpServletRequest setSubjectsContent(HttpServletRequest request) throws SQLException {
        Map<Integer, contents.entities.Subject> subjects = Database.selectSubjects();
        request.setAttribute("subjects", subjects.values());
        return request;
    }
    
    private static HttpServletRequest addSubject(HttpServletRequest request) throws SQLException {
        String subjectName = request.getParameter("subjectName");
        int yearClass = Integer.valueOf(request.getParameter("yearClass")).intValue();
        
        if (!Database.addSubject(subjectName, yearClass)) {
            request.setAttribute("result", "failed");
            request.setAttribute("action", "addSubject");
        } else {
            request.setAttribute("redirect", "subjects");
        }
        return request;
    }
    
    private static HttpServletRequest editSubject(HttpServletRequest request) throws SQLException {
        int subjectId = Integer.valueOf(request.getParameter("subjectId")).intValue();
        String subjectName = request.getParameter("subjectName");
        int yearClass = Integer.valueOf(request.getParameter("yearClass")).intValue();
        
        if (!Database.editSubject(subjectId, subjectName, yearClass)) {
            request.setAttribute("result", "failed");
            request.setAttribute("action", "editSubject");
        } else {
            request.setAttribute("redirect", "subjects");
        }
        return request;
    }
    
    private static void deleteSubject(HttpServletRequest request) throws SQLException {
        int subjectId = Integer.valueOf(request.getParameter("subjectId")).intValue();
        
        Database.deleteSubject(subjectId);
    }
    
    private static HttpServletRequest setClassesContent(HttpServletRequest request) throws SQLException {
        String classIdString = request.getParameter("classId");
        if (classIdString == null) {
            Map<Integer, Class> classes = Database.selectClasses();
            request.setAttribute("classes", classes.values());
        } else {
            int classId = Integer.valueOf(classIdString).intValue();
            String className = Database.selectClassName(classId);
            Map<Integer, Subject> allSubjects = Database.selectSubjects();
            List<Integer> subjectsOfClass = Database.selectSubjectIdsOfClass(classId);
            request.setAttribute("className", className);
            request.setAttribute("allSubjects", allSubjects.values());
            request.setAttribute("subjectsOfClass", subjectsOfClass);
        }
        return request;
    }
    
    private static HttpServletRequest addClass(HttpServletRequest request) throws SQLException {
        String className = request.getParameter("className");
        
        if (!Database.addClass(className)) {
            request.setAttribute("result", "failed");
            request.setAttribute("action", "addClass");
        } else {
            request.setAttribute("redirect", "classes");
        }
        return request;
    }
    
    private static HttpServletRequest editClass(HttpServletRequest request) throws SQLException {
        int classId = Integer.valueOf(request.getParameter("classId")).intValue();
        String className = request.getParameter("className");
        List<Integer> subjectIds = new ArrayList<Integer>();
        String[] subjectIdsString = request.getParameterValues("subjectId");
        if (subjectIdsString != null) {
            for (int i = 0; i < subjectIdsString.length; i++) {
                subjectIds.add(Integer.valueOf(subjectIdsString[i]));
            }
        }
        
        if (!Database.editClass(classId, className, subjectIds)) {
            request.setAttribute("result", "failed");
            request.setAttribute("action", "editClass");
        } else {
            request.setAttribute("redirect", "classes");
        }
        return request;
    }
    
    private static HttpServletRequest deleteClass(HttpServletRequest request) throws SQLException {
        int classId = Integer.valueOf(request.getParameter("classId")).intValue();
        
        if (!Database.deleteClass(classId)) {
            request.setAttribute("result", "failed");
            request.setAttribute("action", "deleteClass");
        } else {
            request.setAttribute("redirect", "classes");
        }
        return request;
    }
        
    private static HttpServletRequest setTeachersContent(HttpServletRequest request) throws SQLException {
        Map<Integer, Teacher> teachers = Database.selectTeachers();
        request.setAttribute("teachers", teachers.values());
        
        return request;
    }
    
    private static HttpServletRequest setAddTeacherContent(HttpServletRequest request) throws SQLException {
        Map<Integer, Subject> subjects = Database.selectSubjects();
        request.setAttribute("subjects", subjects.values());
        
        return request;
    }
    
    private static HttpServletRequest addTeacher(HttpServletRequest request) throws SQLException {
        String firstName = request.getParameter("firstName");
        String lastName = request.getParameter("lastName");
        if (firstName.contains("Administrator") || firstName.contains("Administrátor") ||
                lastName.contains("Administrator") || lastName.contains("Administrátor")) {
            request.setAttribute("result", "failed");
            request.setAttribute("action", "addTeacher");
        } else {
            List<Integer> subjectIds = new ArrayList<Integer>();
            String[] subjectIdsString = request.getParameterValues("subjectId");
            if (subjectIdsString != null) {
                for (int i = 0; i < subjectIdsString.length; i++) {
                    subjectIds.add(Integer.valueOf(subjectIdsString[i]));
                }
            }
            
            String username = CommonMethods.generateNewUsername(firstName, lastName);
            String password = CommonMethods.generatePassword();
        
            int teacherId = Database.addTeacher(firstName, lastName, username, CommonMethods.encrypt(password), subjectIds);
            request.setAttribute("redirect", "newTeacherAdded&teacherId=" + teacherId + "&password=" + password);
        }
        
        return request;
    }
    
    private static HttpServletRequest setTeacherAddedContent(HttpServletRequest request) throws SQLException {
        int teacherId = Integer.valueOf(request.getParameter("teacherId")).intValue();
        Teacher teacher = Database.getTeacher(teacherId);
        request.setAttribute("teacher", teacher);
        return request;
    }
    
    private static HttpServletRequest setEditTeacherContent(HttpServletRequest request) throws SQLException {
        int teacherId = Integer.valueOf(request.getParameter("teacherId")).intValue();
        Teacher teacher = Database.getTeacher(teacherId);
        request.setAttribute("teacher", teacher);
        
        Map<Integer, Subject> allSubjects = Database.selectSubjects();
        List<Integer> subjectsOfTeacher = Database.selectSubjectIdsOfTeacher(teacherId);
        request.setAttribute("allSubjects", allSubjects.values());
        request.setAttribute("subjectsOfTeacher", subjectsOfTeacher);
        
        return request;
    }
    
    private static HttpServletRequest editTeacher(HttpServletRequest request) throws SQLException {
        int teacherId = Integer.valueOf(request.getParameter("teacherId")).intValue();
        String firstName = request.getParameter("firstName");
        String lastName = request.getParameter("lastName");
        if (firstName.contains("Administrator") || firstName.contains("Administrátor") ||
                lastName.contains("Administrator") || lastName.contains("Administrátor")) {
            request.setAttribute("result", "failed");
            request.setAttribute("action", "editTeacher");
        } else {
            List<Integer> subjectIds = new ArrayList<Integer>();
            String[] subjectIdsString = request.getParameterValues("subjectId");
            if (subjectIdsString != null) {
                for (int i = 0; i < subjectIdsString.length; i++) {
                    subjectIds.add(Integer.valueOf(subjectIdsString[i]));
                }
            }
        
            Database.editTeacher(teacherId, firstName, lastName, subjectIds);
            request.setAttribute("redirect", "teachers");
        }

        return request;
    }
    
    private static HttpServletRequest createNewPasswordForTeacher(HttpServletRequest request) throws SQLException {
        int teacherId = Integer.valueOf(request.getParameter("teacherId")).intValue();
        String password = CommonMethods.generatePassword();
        
        Database.setNewPasswordHashToUser(teacherId, Database.UserRole.TEACHER, CommonMethods.encrypt(password));
        request.setAttribute("redirect", "newPasswordForTeacherCreated&teacherId=" + teacherId + "&password=" + password);
        
        return request;
    }
    
    private static HttpServletRequest setNewPasswordForTeacherCreatedContent(HttpServletRequest request) throws SQLException {
        int teacherId = Integer.valueOf(request.getParameter("teacherId")).intValue();
        Teacher teacher = Database.getTeacher(teacherId);
        request.setAttribute("teacher", teacher);
        return request;
    }
    
    private static void deleteTeacher(HttpServletRequest request) throws SQLException {
        int teacherId = Integer.valueOf(request.getParameter("teacherId")).intValue();
        
        Database.deleteTeacher(teacherId);
    }
     
    private static HttpServletRequest setStudentsContent(HttpServletRequest request) throws SQLException {
        Map<Integer, ClassesStudents> classesStudents = new HashMap<Integer, ClassesStudents>();
        int i = 1;
        
        Map<Integer, Class> classes = Database.selectClasses();
        for (Map.Entry<Integer, Class> classEntry : classes.entrySet()) {
            Map<Integer, Student> studentsMap = Database.selectStudentsOfClass(classEntry.getValue().getClassId());
            List<Student> students = new ArrayList<Student>();
            for (Map.Entry<Integer, Student> studentEntry : studentsMap.entrySet()) {
                students.add(studentEntry.getValue());
            }

            classesStudents.put(i, new ClassesStudents(classEntry.getValue(), students));
            i++;
        }
        
        request.setAttribute("classesStudents", classesStudents.values());
        return request;
    }
    
    private static HttpServletRequest setAddStudentContent(HttpServletRequest request) throws SQLException {
        Map<Integer, Class> classes = Database.selectClasses();
        request.setAttribute("classes", classes.values());
        
        return request;
    }
    
    private static HttpServletRequest addStudent(HttpServletRequest request) throws SQLException {
        String studentFirstName = request.getParameter("studentFirstName");
        String studentLastName = request.getParameter("studentLastName");
        String parentFirstName = request.getParameter("parentFirstName");
        String parentLastName = request.getParameter("parentLastName");
        if (studentFirstName.contains("Administrator") || studentFirstName.contains("Administrátor") ||
                studentLastName.contains("Administrator") || studentLastName.contains("Administrátor") ||
                parentFirstName.contains("Administrator") || parentFirstName.contains("Administrátor") ||
                parentLastName.contains("Administrator") || parentLastName.contains("Administrátor")) {
            request.setAttribute("result", "failed");
            request.setAttribute("action", "addStudent");
        } else {
            int classId = Integer.valueOf(request.getParameter("classId")).intValue();
            
            String studentUsername = CommonMethods.generateNewUsername(studentFirstName, studentLastName);
            String studentPassword = CommonMethods.generatePassword();
            String parentUsername = CommonMethods.generateNewUsername(parentFirstName, parentLastName);
            String parentPassword = CommonMethods.generatePassword();
        
            int studentId = Database.addStudent(studentFirstName, studentLastName, studentUsername,
                    CommonMethods.encrypt(studentPassword),
                    parentFirstName, parentLastName, parentUsername, CommonMethods.encrypt(parentPassword),
                    classId);
            
            request.setAttribute("redirect", "newStudentAdded&studentId=" + studentId + "&studentPassword=" + studentPassword + "&parentPassword=" + parentPassword);
        }
        
        return request;
    }
    
    private static HttpServletRequest setStudentAddedContent(HttpServletRequest request) throws SQLException {
        int studentId = Integer.valueOf(request.getParameter("studentId")).intValue();
        Student student = Database.getStudent(studentId);
        request.setAttribute("student", student);
        return request;
    }
    
    private static HttpServletRequest setEditStudentContent(HttpServletRequest request) throws SQLException {
        int studentId = Integer.valueOf(request.getParameter("studentId")).intValue();
        Student student = Database.getStudent(studentId);
        request.setAttribute("student", student);
        
        Map<Integer, Class> classes = Database.selectClasses();
        request.setAttribute("classes", classes.values());
        
        return request;
    }
    
    private static HttpServletRequest editStudent(HttpServletRequest request) throws SQLException {
        int studentId = Integer.valueOf(request.getParameter("studentId")).intValue();
        
        String studentFirstName = request.getParameter("studentFirstName");
        String studentLastName = request.getParameter("studentLastName");
        String parentFirstName = request.getParameter("parentFirstName");
        String parentLastName = request.getParameter("parentLastName");
        if (studentFirstName.contains("Administrator") || studentFirstName.contains("Administrátor") ||
                studentLastName.contains("Administrator") || studentLastName.contains("Administrátor") ||
                parentFirstName.contains("Administrator") || parentFirstName.contains("Administrátor") ||
                parentLastName.contains("Administrator") || parentLastName.contains("Administrátor")) {
            request.setAttribute("result", "failed");
            request.setAttribute("action", "editStudent");
        } else {
            int classId = Integer.valueOf(request.getParameter("classId")).intValue();

            Database.editStudent(studentId, studentFirstName, studentLastName, parentFirstName, parentLastName, classId);
            request.setAttribute("redirect", "students");
        }
        
        return request;
    }
    
    private static HttpServletRequest createNewPasswordForStudent(HttpServletRequest request) throws SQLException {
        int studentId = Integer.valueOf(request.getParameter("studentId")).intValue();
        String password = CommonMethods.generatePassword();
        
        Database.setNewPasswordHashToUser(studentId, Database.UserRole.STUDENT, CommonMethods.encrypt(password));
        request.setAttribute("redirect", "newPasswordForStudentCreated&studentId=" + studentId + "&password=" + password);
        
        return request;
    }
    
    private static HttpServletRequest setNewPasswordForStudentCreatedContent(HttpServletRequest request) throws SQLException {
        int studentId = Integer.valueOf(request.getParameter("studentId")).intValue();
        Student student = Database.getStudent(studentId);
        request.setAttribute("student", student);
        return request;
    }
    
    private static HttpServletRequest createNewPasswordForParent(HttpServletRequest request) throws SQLException {
        int studentId = Integer.valueOf(request.getParameter("studentId")).intValue();
        Student student = Database.getStudent(studentId);
        int parentId = student.getParent().getParentId();
        String password = CommonMethods.generatePassword();
        
        Database.setNewPasswordHashToUser(parentId, Database.UserRole.PARENT, CommonMethods.encrypt(password));
        request.setAttribute("redirect", "newPasswordForParentCreated&studentId=" + studentId + "&password=" + password);
        
        return request;
    }
    
    private static HttpServletRequest setNewPasswordForParentCreatedContent(HttpServletRequest request) throws SQLException {
        int studentId = Integer.valueOf(request.getParameter("studentId")).intValue();
        Student student = Database.getStudent(studentId);
        request.setAttribute("student", student);
        return request;
    }
    
    private static void deleteStudent(HttpServletRequest request) throws SQLException {
        int studentId = Integer.valueOf(request.getParameter("studentId")).intValue();
        
        Database.deleteStudent(studentId);
    }
    
    private static HttpServletRequest setTimetablesContent(HttpServletRequest request) throws SQLException {
        Map<Integer, Class> classes = Database.selectClasses();
        request.setAttribute("classes", classes.values());
        return request;
    }
    
    private static HttpServletRequest makeFileOfXMLInformationForTimetables(HttpServletRequest request) 
            throws SQLException, ParserConfigurationException, TransformerConfigurationException, TransformerException, IOException {
        // prepare XML
        javax.xml.parsers.DocumentBuilderFactory factory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
        javax.xml.parsers.DocumentBuilder builder = factory.newDocumentBuilder();
        org.w3c.dom.Document document = builder.newDocument();
        org.w3c.dom.Element root = document.createElement("timetables_information");
        document.appendChild(root);
        
        org.w3c.dom.Element subjects = document.createElement("subjects");
        root.appendChild(subjects);
        org.w3c.dom.Element teachers = document.createElement("teachers");
        root.appendChild(teachers);
        org.w3c.dom.Element classes = document.createElement("classes");
        root.appendChild(classes);
        
        
        Map<Integer, Subject> subjectsList = Database.selectSubjects();
        for (Map.Entry<Integer, Subject> subjectItem : subjectsList.entrySet()) {
            org.w3c.dom.Element subject = document.createElement("subject");
            
            org.w3c.dom.Element subjectId = document.createElement("id");
            subjectId.setTextContent(String.valueOf(subjectItem.getValue().getSubjectId()));
            
            org.w3c.dom.Element subjectName = document.createElement("name");
            subjectName.setTextContent(subjectItem.getValue().getName());
            
            org.w3c.dom.Element subjectYearClass = document.createElement("year-class");
            subjectYearClass.setTextContent(String.valueOf(subjectItem.getValue().getYearClass()));
            
            subject.appendChild(subjectId);
            subject.appendChild(subjectName);
            subject.appendChild(subjectYearClass);

            subjects.appendChild(subject);
        }
        
        Map<Integer, Teacher> teachersList = Database.selectTeachers();
        for (Map.Entry<Integer, Teacher> teacherItem : teachersList.entrySet()) {
            org.w3c.dom.Element teacher = document.createElement("teacher");
            
            org.w3c.dom.Element teacherId = document.createElement("id");
            teacherId.setTextContent(String.valueOf(teacherItem.getValue().getTeacherId()));
            
            org.w3c.dom.Element teacherFirstName = document.createElement("first_name");
            teacherFirstName.setTextContent(teacherItem.getValue().getFirstName());
            org.w3c.dom.Element teacherLastName = document.createElement("last_name");
            teacherLastName.setTextContent(teacherItem.getValue().getLastName());
            
            org.w3c.dom.Element teacherSubjects = document.createElement("subjects");
            
            List<Subject> teacherSubjectsList = teacherItem.getValue().getSubjects();
            for (int i = 0; i < teacherSubjectsList.size(); i++) {
                org.w3c.dom.Element subjectId = document.createElement("subjectId");
                subjectId.setTextContent(String.valueOf(teacherSubjectsList.get(i).getSubjectId()));
                teacherSubjects.appendChild(subjectId);
            }
            
            teacher.appendChild(teacherId);
            teacher.appendChild(teacherFirstName);
            teacher.appendChild(teacherLastName);
            teacher.appendChild(teacherSubjects);

            teachers.appendChild(teacher);
        }
        
        Map<Integer, Class> classesList = Database.selectClasses();
        for (Map.Entry<Integer, Class> classItem : classesList.entrySet()) {
            org.w3c.dom.Element schoolClass = document.createElement("class");
            
            org.w3c.dom.Element classId = document.createElement("id");
            classId.setTextContent(String.valueOf(classItem.getValue().getClassId()));
            
            org.w3c.dom.Element className = document.createElement("name");
            className.setTextContent(classItem.getValue().getName());
            
            org.w3c.dom.Element classSubjects = document.createElement("subjects");
            List<Integer> classSubjectsIdsList = Database.selectSubjectIdsOfClass(classItem.getValue().getClassId());
            for (int i = 0; i < classSubjectsIdsList.size(); i++) {
                org.w3c.dom.Element subjectId = document.createElement("subjectId");
                subjectId.setTextContent(String.valueOf(classSubjectsIdsList.get(i)));
                classSubjects.appendChild(subjectId);
            }
            
            schoolClass.appendChild(classId);
            schoolClass.appendChild(className);
            schoolClass.appendChild(classSubjects);
            
            classes.appendChild(schoolClass);
        }
        
        // transform DOM to XML string
        javax.xml.transform.TransformerFactory transformerFactory = javax.xml.transform.TransformerFactory.newInstance();
        javax.xml.transform.Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "no");
        transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes");
        transformer.setOutputProperty(javax.xml.transform.OutputKeys.ENCODING, "UTF-8");

        java.io.StringWriter stringWriter = new java.io.StringWriter();
        javax.xml.transform.stream.StreamResult result = new javax.xml.transform.stream.StreamResult(stringWriter);
        javax.xml.transform.dom.DOMSource source = new javax.xml.transform.dom.DOMSource(document);
        transformer.transform(source, result);
        String xmlString = stringWriter.toString();
        
        // write XML string to file
        File file = new File(informationForTimetablesFilePath);
        if (!file.exists()) {
            file.createNewFile();
        } else {
            java.io.OutputStreamWriter fileWriter = new java.io.OutputStreamWriter(
                    new java.io.FileOutputStream(file), "UTF-8");
            java.io.BufferedWriter out = new java.io.BufferedWriter(fileWriter);
            out.write(xmlString);
            out.close();
        }
        
        return request;
    }

    public static HttpServletResponse setInformationForTimetablesFileDownloadResponse(HttpServletResponse response) throws IOException {
        response.setContentType("text/plain");
	response.setHeader("Content-Disposition",
                     "attachment;filename=information_for_timetables.xml");
        
        java.io.OutputStream out = response.getOutputStream();
        java.io.FileInputStream in = new java.io.FileInputStream(informationForTimetablesFilePath);
        byte[] buffer = new byte[4096];
        int length;
        while ((length = in.read(buffer)) > 0){
            out.write(buffer, 0, length);
        }
        in.close();
        out.flush();
        
        return response;
    }
    
    public static void deleteTimetable(HttpServletRequest request) throws SQLException {
        int classId = Integer.valueOf(request.getParameter("classId")).intValue();
        Database.deleteTimetableOfClass(classId);
    }
    
    public static HttpServletRequest setTimetable(HttpServletRequest request) throws SQLException {
        int classId = Integer.valueOf(request.getParameter("classId")).intValue();

        File file = new File(FileUploadServlet.getUploadedFilePath());

        try {
            // validate file
            SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
            File schemaFile = new File(ApplicationServlet.getServletPath() + File.separator + "xml" + File.separator + "timetable_file.xsd");
            Schema schema = schemaFactory.newSchema(schemaFile);
            Validator validator = schema.newValidator();
            Source source = new StreamSource(file);        
            validator.validate(source);
            
            // get XML DOM from file
            javax.xml.parsers.DocumentBuilderFactory factory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
            javax.xml.parsers.DocumentBuilder builder = factory.newDocumentBuilder();
            org.w3c.dom.Document document = builder.parse(file);
            document.getDocumentElement().normalize();
            
            // remove file
            file.delete();
            
            // process xml - DOM to list of timetables
            List<database.DatabaseEntities.Timetable> timetables = new ArrayList<database.DatabaseEntities.Timetable>();
            
            NodeList timetableNodesList = document.getElementsByTagName("timetable");
            for (int i = 0; i < timetableNodesList.getLength(); i++) {
                NodeList timetableParametersList = timetableNodesList.item(i).getChildNodes();                
                int subjectId = 0, teacherId = 0, day = 1, unit = 0;
                
                for (int j = 0; j < timetableParametersList.getLength(); j++) {
                    String nodeName = timetableParametersList.item(j).getNodeName();
                    if (nodeName.equals("subject_id")) {
                        subjectId = Integer.valueOf(timetableParametersList.item(j).getTextContent()).intValue();
                    } else if (nodeName.equals("teacher_id")) {
                        teacherId = Integer.valueOf(timetableParametersList.item(j).getTextContent()).intValue();
                    } else if (nodeName.equals("day")) {
                        day = Integer.valueOf(timetableParametersList.item(j).getTextContent()).intValue();
                    } else if (nodeName.equals("unit")) {
                        unit = Integer.valueOf(timetableParametersList.item(j).getTextContent()).intValue();
                    }
                }
                
                database.DatabaseEntities.Timetable timetable = new database.DatabaseEntities.Timetable();
                timetable.subjectId = subjectId;
                timetable.teacherId = teacherId;
                timetable.day = day;
                timetable.unit = unit;
                timetables.add(timetable);
            }
            
            // check for collisions and insert timetables to DB
            boolean isOK = true;
            for (int i = 0; i < timetables.size(); i++) {
                // check for collisions with timetables of this class
                for (int j = i+1; j < timetables.size(); j++) {
                    if (timetables.get(i).day == timetables.get(j).day && timetables.get(i).unit == timetables.get(j).unit) {
                        isOK = false;
                        break;
                    }
                }
                if (!isOK) {
                    break;
                }
                
                // check for validity of timetable
                isOK = Database.isValidTimetable(classId, timetables.get(i));
                if (!isOK) {
                    break;
                }
                
                // check for collisions with timetables of other classes (busy teacher)
                isOK = Database.timetableIsNotInCollision(timetables.get(i));
                if (!isOK) {
                    break;
                }
            }
            
            if (isOK) {
                Database.insertTimetablesForClass(classId, timetables);
                request.setAttribute("redirect", "setTimetableSuccessful&classId=" + classId);
            } else {
                request.setAttribute("result", "failed");
                request.setAttribute("action", "setTimetable");
            }

            return request;
        } catch (SQLException exception) {
            file.delete();
            throw exception;
        } catch (Exception exception) {
            System.err.println("Error occured durign setting of timetable: ");
            exception.printStackTrace();
            file.delete();
            request.setAttribute("result", "failed");
            request.setAttribute("action", "setTimetable");
            return request;
        }
    }
    
    private static HttpServletRequest setTimetableSetSuccessfulContent(HttpServletRequest request) throws SQLException {
        int classId = Integer.valueOf(request.getParameter("classId")).intValue();
        String className = Database.selectClassName(classId);
        request.setAttribute("className", className);
        
        return request;
    }
    
    private AdminContent() {
    }
}
